// utils/errorHandler.js - 统一异常处理工具

/**
 * 异常代码定义
 */
const ERROR_CODES = {
  // 授权相关
  NEED_USER_AUTH: [2001, 2004],
  // 登录相关
  NEED_LOGIN: [401, 403],
  // 网络相关
  NETWORK_ERROR: [500, 502, 503, 504],
  // 业务错误
  BUSINESS_ERROR: [400, 422, 500],
};

/**
 * 授权类型定义
 */
const AUTH_TYPES = {
  USER_INFO: "userInfo",
  LOCATION: "location",
  CAMERA: "camera",
  PHONE: "phone",
  ADDRESS: "address",
};

/**
 * 检查异常类型
 * @param {Object} error 异常对象
 * @returns {string} 异常类型
 */
const getErrorType = (error) => {
  if (!error || !error.code) {
    return "UNKNOWN";
  }

  const code = error.code;

  if (ERROR_CODES.NEED_USER_AUTH.includes(code)) {
    return "NEED_USER_AUTH";
  }

  if (ERROR_CODES.NEED_LOGIN.includes(code)) {
    return "NEED_LOGIN";
  }

  if (ERROR_CODES.NETWORK_ERROR.includes(code)) {
    return "NETWORK_ERROR";
  }

  return "BUSINESS_ERROR";
};

/**
 * 处理用户授权
 * @param {string} authType 授权类型
 * @param {string} desc 授权描述
 * @returns {Promise} 授权结果
 */
const handleUserAuth = (
  authType = AUTH_TYPES.USER_INFO,
  desc = "用于完善用户资料"
) => {
  return new Promise((resolve, reject) => {
    wx.showModal({
      title: "需要授权",
      content: "为了更好的服务体验，需要获取您的授权信息",
      confirmText: "去授权",
      cancelText: "取消",
      success: (res) => {
        if (res.confirm) {
          performAuth(authType, desc).then(resolve).catch(reject);
        } else {
          reject(new Error("用户取消授权"));
        }
      },
    });
  });
};

/**
 * 执行具体的授权操作
 * @param {string} authType 授权类型
 * @param {string} desc 授权描述
 * @returns {Promise} 授权结果
 */
const performAuth = (authType, desc) => {
  return new Promise((resolve, reject) => {
    switch (authType) {
      case AUTH_TYPES.USER_INFO:
        wx.getUserProfile({
          desc: desc,
          success: (userRes) => {
            console.log("用户信息授权成功:", userRes);
            resolve(userRes);
          },
          fail: (err) => {
            console.error("用户信息授权失败:", err);
            reject(err);
          },
        });
        break;

      case AUTH_TYPES.LOCATION:
        wx.getLocation({
          type: "wgs84",
          success: (locationRes) => {
            console.log("位置信息授权成功:", locationRes);
            resolve(locationRes);
          },
          fail: (err) => {
            console.error("位置信息授权失败:", err);
            reject(err);
          },
        });
        break;

      case AUTH_TYPES.CAMERA:
        wx.chooseImage({
          count: 1,
          sizeType: ["compressed"],
          sourceType: ["camera"],
          success: (cameraRes) => {
            console.log("相机授权成功:", cameraRes);
            resolve(cameraRes);
          },
          fail: (err) => {
            console.error("相机授权失败:", err);
            reject(err);
          },
        });
        break;

      case AUTH_TYPES.PHONE:
        wx.getPhoneNumber({
          success: (phoneRes) => {
            console.log("手机号授权成功:", phoneRes);
            resolve(phoneRes);
          },
          fail: (err) => {
            console.error("手机号授权失败:", err);
            reject(err);
          },
        });
        break;

      case AUTH_TYPES.ADDRESS:
        wx.chooseAddress({
          success: (addressRes) => {
            console.log("地址授权成功:", addressRes);
            resolve(addressRes);
          },
          fail: (err) => {
            console.error("地址授权失败:", err);
            reject(err);
          },
        });
        break;

      default:
        wx.showToast({
          title: "暂不支持的授权类型",
          icon: "none",
        });
        reject(new Error("不支持的授权类型"));
    }
  });
};

/**
 * 显示错误信息
 * @param {string} message 错误信息
 * @param {string} type 错误类型
 */
const showError = (message, type = "toast") => {
  if (type === "modal") {
    wx.showModal({
      title: "提示",
      content: message,
      showCancel: false,
      confirmText: "确定",
    });
  } else {
    wx.showToast({
      title: message,
      icon: "none",
      duration: 3000,
    });
  }
};

/**
 * 统一异常处理
 * @param {Object} error 异常对象
 * @param {Object} options 处理选项
 * @returns {Promise} 处理结果
 */
const handleError = async (error, options = {}) => {
  const {
    showError: shouldShowError = true,
    errorType: customErrorType = null,
    authType = AUTH_TYPES.USER_INFO,
    onAuthSuccess = null,
    onAuthFail = null,
  } = options;

  const errorType = customErrorType || getErrorType(error);

  console.error("异常处理:", {
    error,
    errorType,
    message: error?.message || "未知错误",
  });

  switch (errorType) {
    case "NEED_USER_AUTH":
      try {
        const authResult = await handleUserAuth(authType);
        if (onAuthSuccess) {
          onAuthSuccess(authResult);
        }
        return { success: true, type: "auth_success", data: authResult };
      } catch (authError) {
        console.error("用户授权失败:", authError);
        if (shouldShowError) {
          showError("授权失败，无法继续操作", "toast");
        }
        if (onAuthFail) {
          onAuthFail(authError);
        }
        return { success: false, type: "auth_fail", error: authError };
      }

    case "NEED_LOGIN":
      if (shouldShowError) {
        wx.showModal({
          title: "需要登录",
          content: "请先登录后再进行操作",
          confirmText: "去登录",
          cancelText: "取消",
          success: (res) => {
            if (res.confirm) {
              // 跳转到个人中心页面进行登录
              wx.switchTab({
                url: "/pages/profile/profile",
              });
            }
          },
        });
      }
      return { success: false, type: "need_login", error };

    case "NETWORK_ERROR":
      if (shouldShowError) {
        showError("网络连接异常，请检查网络后重试", "toast");
      }
      return { success: false, type: "network_error", error };

    case "BUSINESS_ERROR":
    default:
      if (shouldShowError) {
        const errorMessage =
          error?.message || error?.data?.message || "操作失败";
        showError(errorMessage, "toast");
      }
      return { success: false, type: "business_error", error };
  }
};

/**
 * 创建异常处理装饰器
 * @param {Function} fn 原函数
 * @param {Object} options 处理选项
 * @returns {Function} 装饰后的函数
 */
const withErrorHandler = (fn, options = {}) => {
  return async (...args) => {
    try {
      return await fn(...args);
    } catch (error) {
      return await handleError(error, options);
    }
  };
};

module.exports = {
  ERROR_CODES,
  AUTH_TYPES,
  getErrorType,
  handleUserAuth,
  showError,
  handleError,
  withErrorHandler,
};
